package utils;

import java.util.Arrays;
import utils.db.CatalogsInserts;

public class ListUtil {
    
    public ListUtil() { }

    public static final String[][] ATOM_LIST =
    {
        {"N", "CA", "C", "O", "CB"}, //ALA
        {"N", "CA", "C", "O", "CB", "CG", "CD", "NE", "CZ", "NH1", "NH2"}, //ARG
        {"N", "CA", "C", "O", "CB", "CG", "OD1", "ND2"}, //ASN
        {"N", "CA", "C", "O", "CB", "CG", "OD1", "OD2"}, //ASP
        {"N", "CA", "C", "O", "CB", "SG"}, //CYS
        {"N", "CA", "C", "O", "CB", "CG", "CD", "OE1", "NE2"}, //GLN
        {"N", "CA", "C", "O", "CB", "CG", "CD", "OE1", "OE2"}, //GLU
        {"N", "CA", "C", "O"}, //GLY
        {"N", "CA", "C", "O", "CB", "CG", "ND1", "CD2", "CE1", "NE2"}, //HIS
        {"N", "CA", "C", "O", "CB", "CG1", "CG2", "CD1"}, //ILE
        {"N", "CA", "C", "O", "CB", "CG", "CD1", "CD2"}, //LEU
        {"N", "CA", "C", "O", "CB", "CG", "CD", "CE", "NZ"}, //LYS
        {"N", "CA", "C", "O", "CB", "CG", "SD", "CE"}, //MET
        {"N", "CA", "C", "O", "CB", "CG", "CD1", "CD2", "CE1", "CE2", "CZ"}, //PHE
        {"N", "CA", "C", "O", "CB", "CG", "CD"}, //PRO
        {"N", "CA", "C", "O", "CB", "OG"}, //SER
        {"N", "CA", "C", "O", "CB", "OG1", "CG2"}, //THR
        {"N", "CA", "C", "O", "CB", "CG", "CD1", "CD2", "NE1", "CE2", "CE3", "CZ2", "CZ3", "CH2"}, //TRP
        {"N", "CA", "C", "O", "CB", "CG", "CD1", "CD2", "CE1", "CE2", "CZ", "OH"}, //TYR
        {"N", "CA", "C", "O", "CB", "CG1", "CG2"} //VAL
    };
    public static final String[][] SIDE_CHAIN_ATOM_LIST =
    {                                                       
        {"N", "CA", "CB"}, //ALA                            
        {"N", "CA", "CB", "CG", "CD", "NE", "CZ"}, //ARG    
        {"N", "CA", "CB", "CG", "OD1"}, //ASN               
        {"N", "CA", "CB", "CG", "OD1"}, //ASP
        {"N", "CA", "CB", "SG"}, //CYS
        {"N", "CA", "CB", "CG", "CD", "OE1"}, //GLN
        {"N", "CA", "CB", "CG", "CD", "OE1"}, //GLU
        {"N", "CA"}, //GLY
        {"N", "CA", "CB", "CG", "ND1"}, //HIS
        {"N", "CA", "CB", "CG1", "CD1"}, //ILE
        {"N", "CA", "CB", "CG", "CD1"}, //LEU
        {"N", "CA", "CB", "CG", "CD", "CE", "NZ"}, //LYS
        {"N", "CA", "CB", "CG", "SD", "CE"}, //MET
        {"N", "CA", "CB", "CG", "CD1"}, //PHE
        {"N", "CA", "CB", "CG", "CD"}, //PRO
        {"N", "CA", "CB", "OG"}, //SER
        {"N", "CA", "CB", "OG1"}, //THR
        {"N", "CA", "CB", "CG", "CD1"}, //TRP
        {"N", "CA", "CB", "CG", "CD1"}, //TYR
        {"N", "CA", "CB", "CG1"} //VAL
    };
    public static final String[] THREE_LETTER_CODE = {"ALA", "ARG", "ASN",
        "ASP", "CYS", "GLN", "GLU", "GLY", "HIS", "ILE", "LEU", "LYS", "MET",
        "PHE", "PRO", "SER", "THR", "TRP", "TYR", "VAL"};
    public static final char[] ONE_LETTER_CODE = {'A', 'R', 'N', 'D', 'C', 'Q',
        'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 'S', 'T', 'W', 'Y', 'V'};
    public static final String[] AA_NAME = {"alanine", "arginine",
        "asparagine", "aspartic acid", "cysteine", "glutamine", "glutamic acid",
        "glycine", "histidine", "isoleucine", "leucine", "lysine", "methionine",
        "phenilalanine", "proline", "serine", "threonine", "triptophan",
        "tyrosine", "valine"};

    //ORDER BY THREE_LETTER_CODE
    //Miller, S., Janin, J., Lesk, A.M. & Chothia, C.
    //Interior and surface of monomeric proteins.
    //Journal of Molecular Biology 196, 641-656 (1987).
    public static final int[] AA_MAX_ACC = {113, 241, 158, 151, 140, 189, 183, 85, 194, 182, 180, 211, 204, 218, 143, 122, 146, 259, 229, 160};

    public static boolean isAminoAcid(String aminoAcid) {
        int i = Arrays.binarySearch(THREE_LETTER_CODE, aminoAcid);
        
        if (i < 0 || i > 19) {
           return false;
        } else {
           return THREE_LETTER_CODE[i].equalsIgnoreCase(aminoAcid);
        }
    }  
     
    /**
    * Obtain the radius of an aminoacid given its name  
    * @param aminoacidName the name of the aminoacid 
    * @return the radius of the aminoacid
    */
    public static double aminoRadius(String aminoacidName){
        double aminoRadius =0.0;
        int aminoacidIndex =0;    
        aminoacidIndex = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aminoacidName);
               
        switch(aminoacidIndex){
            case 1:{aminoRadius = 6.078992888923319;    break;}//ARG    4.766923838231473;
            case 2:{aminoRadius = 2.464769360406774;    break;}//ASN    2.4647693604067706;
            case 3:{aminoRadius = 2.398278757776087;    break;}//ASP    2.398278757776084;
            case 4:{aminoRadius = 1.8080000000000025;   break;}//CYS    1.8079999999999987;
            case 5:{aminoRadius = 3.7720098170014467;   break;}//GLN    3.4754370197573095;
            case 6:{aminoRadius = 3.6876194269018296;   break;}//GLU    3.523499723534706;
            case 8:{aminoRadius = 3.665834004731916;    break;}//HIS    3.66583400473191;
            case 9:{aminoRadius = 2.5535366061336466;   break;}//ILE    2.5535366061336444;
            case 10:{aminoRadius= 2.5098814367232682;   break;}//LEU    2.509881436723265;
            case 11:{aminoRadius= 5.002904931966784;    break;}//LYS    3.9890936086406814;
            case 12:{aminoRadius= 4.175037509360442;    break;}//MET    3.2813512141228705;
            case 13:{aminoRadius= 4.2669351626152325;   break;}//PHE    4.26693516261523;
            case 14:{aminoRadius= 2.393494497373622;    break;}//PRO    2.3934944973736227;
            case 15:{aminoRadius= 1.4170000000000023;   break;}//SER    1.417;
            case 16:{aminoRadius= 1.521000000000001;    break;}//THR    1.5210000000000006;
            case 17:{aminoRadius= 5.36946986234476;     break;}//TRP    5.369469862344756;
            case 18:{aminoRadius= 5.653435631181081;    break;}//TYR    5.6534356311810745
            case 19:{aminoRadius= 1.5210000000000017;   break;}//VAL    1.5210000000000004;
            default:{aminoRadius= 1.417;                break;}//ALA or GLY
       }
       return aminoRadius;
    }
    
    public static double getIndexRotamer_aminoRadius(String aminoacidName){
        double maxRotamerIndex =0.0;
        int aminoacidIndex =0;    
        aminoacidIndex = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aminoacidName);
               
        switch(aminoacidIndex){
            case 1:{maxRotamerIndex = 10;  break;}//ARG   
            case 2:{maxRotamerIndex = 7;   break;}//ASN
            case 3:{maxRotamerIndex = 0;   break;}//ASP
            case 4:{maxRotamerIndex = 0;   break;}//CYS   
            case 5:{maxRotamerIndex = 17;  break;}//GLN   
            case 6:{maxRotamerIndex = 13;  break;}//GLU   
            case 8:{maxRotamerIndex = 0;   break;}//HIS   
            case 9:{maxRotamerIndex = 7;   break;}//ILE  
            case 10:{maxRotamerIndex= 5;   break;}//LEU   
            case 11:{maxRotamerIndex= 31;  break;}//LYS   
            case 12:{maxRotamerIndex= 1;   break;}//MET  
            case 13:{maxRotamerIndex= 5;   break;}//PHE  
            case 14:{maxRotamerIndex= 0;   break;}//PRO   
            case 15:{maxRotamerIndex= 2;   break;}//SER   
            case 16:{maxRotamerIndex= 2;   break;}//THR   
            case 17:{maxRotamerIndex= 6;   break;}//TRP   
            case 18:{maxRotamerIndex= 4;   break;}//TYR   
            case 19:{maxRotamerIndex= 2;   break;}//VAL    
            default:{maxRotamerIndex= 0;   break;}//ALA or GLY
       }
       return maxRotamerIndex;
    }
    
    public static double MaxRotamerProb(String aminoacidName) {
        double maxPro =0.0;
        int aminoacidIndex =0;    
        aminoacidIndex = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aminoacidName);
               
        switch(aminoacidIndex){
            case 1:{    maxPro = 10.99;     break;}//ARG
            case 2:{    maxPro = 28.20;     break;}//ASN
            case 3:{    maxPro = 30.87;     break;}//ASP
            case 4:{    maxPro = 56.64;     break;}//CYS
            case 5:{    maxPro = 18.53;     break;}//GLN
            case 6:{    maxPro = 18.84;     break;}//GLU
            case 8:{    maxPro = 29.64;     break;}//HIS
            case 9:{    maxPro = 61.58;     break;}//ILE
            case 10:{   maxPro = 62.52;     break;}//LEU
            case 11:{   maxPro = 22.79;     break;}//LYS
            case 12:{   maxPro = 18.53;     break;}//MET
            case 13:{   maxPro = 47.08;     break;}//PHE
            case 14:{   maxPro = 50.72;     break;}//PRO
            case 15:{   maxPro = 47.07;     break;}//SER
            case 16:{   maxPro = 48.86;     break;}//THR
            case 17:{   maxPro = 30.81;     break;}//TRP
            case 18:{   maxPro = 47.35;     break;}//TYR
            case 19:{   maxPro = 73.90;     break;}//VAL
            default:{   maxPro = 0;         break;}//ALA or GLY
        }

        return maxPro;
    }

    static public void main(String[] args)  {
        CatalogsInserts catIns = new CatalogsInserts();
        for (int i = 0; i < THREE_LETTER_CODE.length; i++) {
            int aminoAcidId = catIns.insertAminoAcid(ONE_LETTER_CODE[i], THREE_LETTER_CODE[i], AA_NAME[i], AA_MAX_ACC[i]);
            for (int j = 0; j < ATOM_LIST[i].length; j++)
                catIns.insertAtom(aminoAcidId, ATOM_LIST[i][j], ATOM_LIST[i][j].charAt(0) + "");
        }
    }
}